package com.cennavi.minenavidemo.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;

import com.cennavi.minenavidemo.R;
import com.cennavi.minenavidemo.utils.TmcBarSegment;
import com.cennavi.minenavidemo.utils.Utils;
import com.minedata.minenavi.navi.TmcSections;

import java.util.ArrayList;

/**
 * 导航界面路况条控件
 */
public class TmcBar extends RelativeLayout {
	private final String TAG = "[TmcBar]";
	private Paint mDrawContentPaint, mPublicPaint;

	TmcSections mTmcSections;
	ArrayList<TmcBarSegment> mTmcBarSegments = new ArrayList<>();

	//车标
	private Bitmap mCarIcon = null;
	//绘制内边距
	private int mDrawPadding = 3;
	//大圆半径
	private float mBigCircleRadius = 0;
	//小圆半径
	private float mSmallCircleRadius = 0;
	//裁剪区域
	Path mClipPath = null;
	//行程百分比
	private float mRatio = 0.0f;
	//暂存的tmc绘制结果
	private Bitmap mSavedTmcMap = null;
	//tmc是否更新
	private boolean mIsTmcUpdated = true;
	//布局控件宽高
	private int mWidth = -1;
	private int mHeight = -1;
	//CarIcon的宽高 高的半值
	private boolean mIsCarIconWidthInited;
	private int mCarIconHeight = 0;
	private int mCarIconWidth = 0;
	private float mHalfCarIconHeight = 0;

	//tmc上下圆弧大小
	private float mTopBottomArcAngle;
	private Utils mUtils;

	public TmcBar(Context context) {
		this(context, null);
	}

	public TmcBar(Context context, @Nullable AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public TmcBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		mUtils = Utils.getInstance();
		mDrawPadding = getPaddingLeft();
		mCarIcon = BitmapFactory.decodeResource(getResources(), R.drawable.small_car_icon);
		initPaint();
	}

	private void initPaint() {
		mPublicPaint = new Paint();
		mDrawContentPaint = new Paint();
	}

	public void setTmcSections(final TmcSections tmcSections) {
		int width = getWidth();
		int height = getHeight();
		if (height < width) {
			mTmcSections = tmcSections;
			int[] tempPixels = mTmcSections.pixels;
			int[] pixels = new int[tempPixels.length];
			for (int i = 0; i < tempPixels.length; i++) {
				pixels[i] = width * tempPixels[i] / 100;
			}
			int[] states = mTmcSections.states;
			mTmcBarSegments.clear();

			for (int i = 0; i < mTmcSections.length; i++) {
				TmcBarSegment tmcBarSegment = new TmcBarSegment();
				tmcBarSegment.colorStates = states[i];
				int left = i > 0 ? pixels[i - 1] : 0;
				int top = 0;
				int right = pixels[i];
				int bottom = height;
				RectF rect = new RectF(left, top, right, bottom);
				tmcBarSegment.rect = rect;
				mTmcBarSegments.add(tmcBarSegment);
			}
		} else {
			mIsTmcUpdated = true;
			if (getWidth() != mWidth || getHeight() != mHeight) {
				reMeasure();
			}
			if (tmcSections.pixels.length == 0) {
				//防止离线算路时，tmc信息不能及时获取到而引发崩溃
				mTmcSections = new TmcSections(new int[]{mHeight}, new int[]{TmcSections.State.unknown});
			}
			mTmcSections = tmcSections;
			int[] tempPixels = new int[mTmcSections.pixels.length];
			//此时tmcSections.pixels为各段所占百分比
			for (int i = 0; i < tmcSections.length; i++) {
				tempPixels[i] = tmcSections.pixels[i] * getHeight() / 100;
			}

			float[] pixels = new float[tempPixels.length];

			float totalPixels = (float) tempPixels[tempPixels.length - 1];

			for (int i = 0; i < tempPixels.length; i++) {
				pixels[i] = tempPixels[i] / totalPixels * 1;
			}
			int[] states = mTmcSections.states;
			mTmcBarSegments.clear();

			float totalHeight = height - mCarIconHeight;
			for (int i = 0; i < mTmcSections.length; i++) {
				TmcBarSegment tmcBarSegment = new TmcBarSegment();
				tmcBarSegment.colorStates = states[i];
				float left;
				float top;
				float right;
				float bottom;

				float from = i == 0 ? 0 : totalHeight * pixels[i - 1];
				float lengthRate = i == 0 ? pixels[0] : pixels[i] - pixels[i - 1];
				left = mDrawPadding;
				top = height - lengthRate * totalHeight - mHalfCarIconHeight - from;
				right = width - mDrawPadding;
				bottom = top + lengthRate * totalHeight;

				RectF rect = new RectF(left, top, right, bottom);
				tmcBarSegment.rect = rect;
				mTmcBarSegments.add(tmcBarSegment);
			}
		}
		invalidate();
	}

	/**
	 * 设置TmcBar外部圆角弧度,不设置或者传入0都显示半圆
	 */
	public void setTmcBarArcAngle(int arcAngle) {
		mTopBottomArcAngle = mUtils.dp2Px(arcAngle);
		reMeasure();
		invalidate();
	}

	/**
	 * 设置绘制内边距(单位：px)
	 */
	public void setDrawPadding(int drawPadding) {
		mDrawPadding = drawPadding;
		reMeasure();
		invalidate();
	}

	//将背景图板绘制到bitmap中
	private void drawTmcMap2Bitmap(Canvas canvas) {
		mPublicPaint.reset();
		mPublicPaint.setColor(Color.WHITE);
		//绘制背景白框
		float centerX = 0.5f * mWidth;
		float topBottomArcAngle = mTopBottomArcAngle == 0 || mTopBottomArcAngle > mWidth ? centerX : mTopBottomArcAngle;
		float topCircleX = centerX;
		float topCircleY = mHalfCarIconHeight + mSmallCircleRadius;
		float bottomCircleX = centerX;
		float bottomCircleY = mHeight - (mHalfCarIconHeight + mSmallCircleRadius);

		RectF topRectF = new RectF(topCircleX - mBigCircleRadius, topCircleY - mBigCircleRadius
				, centerX + mBigCircleRadius, topCircleY + mBigCircleRadius);
		canvas.drawRoundRect(topRectF, topBottomArcAngle, topBottomArcAngle, mPublicPaint); // 画top圆

		RectF bottomRectF = new RectF(bottomCircleX - mBigCircleRadius, bottomCircleY - mSmallCircleRadius
				, bottomCircleX + mBigCircleRadius, bottomCircleY + mSmallCircleRadius + mDrawPadding); // 加上margin是为了和外框有边距
		canvas.drawRoundRect(bottomRectF, topBottomArcAngle, topBottomArcAngle, mPublicPaint); // 画bottom圆

		RectF rectF = new RectF(0, mHalfCarIconHeight + mSmallCircleRadius, mWidth, mHeight - (mHalfCarIconHeight + mSmallCircleRadius));
		canvas.drawRect(rectF, mPublicPaint);

		canvas.save();
		canvas.clipPath(mClipPath, Region.Op.DIFFERENCE);
		for (int i = 0; i < mTmcBarSegments.size(); i++) {
			TmcBarSegment tmcBarSegment = mTmcBarSegments.get(i);
			canvas.drawRect(tmcBarSegment.rect, getPaint(tmcBarSegment.colorStates));
		}
		canvas.restore();
	}

	//reset mWidth and mHeight,and reset clipPath
	private void reMeasure() {

		mWidth = getWidth();
		mHeight = getHeight();
		mBigCircleRadius = 0.5f * mWidth;
		mSmallCircleRadius = mBigCircleRadius - mDrawPadding;
		float center = 0.5f * mWidth;
		float topBottomArcAngle = mTopBottomArcAngle == 0 || mTopBottomArcAngle > mWidth ? center : mTopBottomArcAngle;

		mClipPath = new Path();
		Path temPath = new Path();
		RectF rectTop = new RectF(0, 0, mWidth, mHalfCarIconHeight + mSmallCircleRadius);
		RectF rectBottom = new RectF(0, mHeight - (mHalfCarIconHeight + mSmallCircleRadius), mWidth, mHeight);
		mClipPath.addRect(rectTop, Path.Direction.CW);
		mClipPath.addRect(rectBottom, Path.Direction.CW);
		float topCircleX = center;
		float topCircleY = mHalfCarIconHeight + mSmallCircleRadius;
		float bottomCircleX = center;
		float bottomCircleY = mHeight - (mHalfCarIconHeight + mSmallCircleRadius);

		RectF topRectF = new RectF(topCircleX - mSmallCircleRadius, topCircleY - mSmallCircleRadius
				, topCircleX + mSmallCircleRadius, topCircleY + mSmallCircleRadius);
		RectF bottomRectF = new RectF(bottomCircleX - mSmallCircleRadius, bottomCircleY - mSmallCircleRadius
				, bottomCircleX + mSmallCircleRadius, bottomCircleY + mSmallCircleRadius);
		temPath.addRoundRect(topRectF, topBottomArcAngle, topBottomArcAngle, Path.Direction.CW);
		temPath.addRoundRect(bottomRectF, topBottomArcAngle, topBottomArcAngle, Path.Direction.CW);
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
			mClipPath.op(temPath, Path.Op.DIFFERENCE);
		}
	}

	public void updateRatio(float ratio) {
		if ((int) (this.mRatio * 1000) == (int) (ratio * 1000) && ratio != 0) {
			return;
		}
		this.mRatio = ratio;
		invalidate();
	}

	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (mTmcBarSegments.size() == 0) {
			return;
		}
		int width = getWidth();
		int height = getHeight();
		if (height < width) {
			for (int i = 0; i < mTmcBarSegments.size(); i++) {
				TmcBarSegment tmcBarSegment = mTmcBarSegments.get(i);
				canvas.drawRect(tmcBarSegment.rect, getPaint(tmcBarSegment.colorStates));
			}
		} else {
			if (mTmcBarSegments.size() == 0) {
				return;
			}

			if (!mIsCarIconWidthInited) {
				// 获得图片的宽高
				int originalCarIconWidth = mCarIcon.getWidth();
				int originalCarIconHeight = mCarIcon.getHeight();
				// 计算缩放比例
				float scaleWidth = (float) Math.round(width * 10 / originalCarIconWidth) / 10;
				float scaleHeight = scaleWidth;
				Matrix matrix = new Matrix();
				matrix.postScale(scaleWidth, scaleHeight);
				// 得到新的图片
				mCarIcon = Bitmap.createBitmap(mCarIcon, 0, 0, originalCarIconWidth, originalCarIconHeight, matrix, true);
				mCarIconHeight = mCarIcon.getHeight();
				mCarIconWidth = mCarIcon.getWidth();
				mHalfCarIconHeight = 0.5f * mCarIconHeight;
				reMeasure();
				mIsCarIconWidthInited = true;
			}

			if (getWidth() != mWidth || getHeight() != mHeight) {
				reMeasure();
			}

			if (mIsTmcUpdated) {
				mSavedTmcMap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
				Canvas temCanvas = new Canvas(mSavedTmcMap);
				drawTmcMap2Bitmap(temCanvas);
				mIsTmcUpdated = false;
			}

			mPublicPaint.reset();
			Rect src = new Rect(0, 0, mWidth, mHeight);
			canvas.drawBitmap(mSavedTmcMap, src, src, mPublicPaint);
			drawGray(canvas);
			Rect srcIcon = new Rect(0, 0, mCarIconWidth, mCarIconHeight);
			float totalHeight = mHeight - mCarIconHeight;
			float from = mHeight - mHalfCarIconHeight - mRatio * totalHeight;
			canvas.drawBitmap(mCarIcon, srcIcon, getLocRect(from), mPublicPaint);
		}
	}

	private void drawGray(Canvas canvas) {
		canvas.save();
		mPublicPaint.reset();
		mPublicPaint.setColor(Color.GRAY);
		float totalHeight = mHeight - mCarIconHeight;
		float from = mHeight - mHalfCarIconHeight - totalHeight * mRatio;
		float to = mHeight - mHalfCarIconHeight - totalHeight * 0;
		float left = mDrawPadding;
		float right = mWidth - left;
		RectF grayRectF = new RectF(left, from, right, to);
		canvas.clipPath(mClipPath, Region.Op.DIFFERENCE);
		canvas.drawRect(grayRectF, mPublicPaint);
		canvas.restore();
	}

	private RectF getLocRect(float dot) {
		float left = 0 + (float) (mWidth - mCarIconWidth) / 2f;
		float right = mWidth - (float) (mWidth - mCarIconWidth) / 2f;
		float top = dot - (float) mCarIconHeight / 2f;
		float bottom = dot + (float) mCarIconHeight / 2f;
		return new RectF(left, top, right, bottom);
	}

	/**
	 * @param state 见{@link TmcSections.State}
	 * @return
	 */
	public Paint getPaint(int state) {
		mDrawContentPaint.reset();
		switch (state) {
			case TmcSections.State.light:
				mDrawContentPaint.setColor(Color.parseColor("#5CE517"));//绿色
				break;
			case TmcSections.State.medium:
				mDrawContentPaint.setColor(Color.parseColor("#FFD400"));//黄色
				break;
			case TmcSections.State.heavy:
				mDrawContentPaint.setColor(Color.parseColor("#FF4C4C"));//红
				break;
			case TmcSections.State.blocked:
				mDrawContentPaint.setColor(Color.parseColor("#701200"));//黑色
				break;
			case TmcSections.State.unknown:
			case TmcSections.State.none:
				mDrawContentPaint.setColor(Color.parseColor("#006FFF"));//蓝色
				break;
			default:
				mDrawContentPaint.setColor(Color.parseColor("#006FFF"));
				break;
		}
		return mDrawContentPaint;
	}
}